package pdf;

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.exceptions.COSVisitorException;

import org.apache.pdfbox.pdfparser.PDFStreamParser;
import org.apache.pdfbox.pdfwriter.ContentStreamWriter;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

import org.apache.pdfbox.pdmodel.common.PDStream;

import org.apache.pdfbox.util.PDFOperator;


/**
 * This is an example that will replace a string in a PDF with a new one.
 *
 * The example is taken from the pdf file format specification.
 *
 * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
 * @version $Revision: 1.3 $
 */
public class PDFModifier
{
    /**
     * Constructor.
     */
    public PDFModifier()
    {
        super();
    }

    /**
     * Locate a string in a PDF and replace it with a new string.
     *
     * @param inputFile The PDF to open.
     * @param outputFile The PDF to write to.
     * @param strToFind The string to find in the PDF document.
     * @param message The message to write in the file.
     *
     * @throws IOException If there is an error writing the data.
     * @throws COSVisitorException If there is an error writing the PDF.
     */
    public void doIt( String inputFile, String outputFile, String strToFind, String message)
        throws IOException, COSVisitorException
        {
    	// the document
    	PDDocument doc = null;
    	try
    	{
    		doc = PDDocument.load( inputFile );
    		List pages = doc.getDocumentCatalog().getAllPages();
    		for( int i=0; i<pages.size(); i++ )
    		{
    			boolean isSkipAlarmOn=false;
    			PDPage page = (PDPage)pages.get( i );
    			PDStream contents = page.getContents();
    			PDFStreamParser parser = new PDFStreamParser(contents.getStream() );
    			parser.parse();
    			List tokens = parser.getTokens();
    			for( int j=0; j<tokens.size(); j++ )
    			{
    				
    				Object next = tokens.get( j );
    				if( next instanceof PDFOperator )
    				{
    					
    					
    					
    					PDFOperator op = (PDFOperator)next;
    					//Tj and TJ are the two operators that display
    					//strings in a PDF
    					if( op.getOperation().equals( "Tj" ) )
    					{
    						//Tj takes one operator and that is the string
    						//to display so lets update that operator
    						COSString previous = (COSString)tokens.get( j-1 );
    						String string = previous.getString();
    						//System.out.println("if block >> "+string);
    						string = string.replaceFirst( strToFind, message );
    						previous.reset();
    						
    						if(string.contains("Your Response")){
    							isSkipAlarmOn=true;
    						}   
    						
    						if(string.contains("(Q.")){
    							isSkipAlarmOn=false;
    						}
    						
    						if(!isSkipAlarmOn)
    						previous.append( string.getBytes() );
    						
    					}
    					else if( op.getOperation().equals( "TJ" ) )
    					{
    						COSArray previous = (COSArray)tokens.get( j-1 );
    						for( int k=0; k<previous.size(); k++ )
    						{
    							Object arrElement = previous.getObject( k );
    							if( arrElement instanceof COSString )
    							{
    								COSString cosString = (COSString)arrElement;
    								String string = cosString.getString();
    								string = string.replaceFirst( strToFind, message );
    								//System.out.println("else block >> "+string);
    								cosString.reset();
    								
    								if(string.contains("Your Response")){
    	    							isSkipAlarmOn=true;
    	    						}   
    	    						
    	    						if(string.contains("(Q.")){
    	    							isSkipAlarmOn=false;
    	    						}
    	    						
    	    						if(!isSkipAlarmOn)
    								cosString.append( string.getBytes() );
    	    						
    							}
    						}
    					}
    				}
    			}
    			//now that the tokens are updated we will replace the
    			//page content stream.
    			PDStream updatedStream = new PDStream(doc);
    			OutputStream out = updatedStream.createOutputStream();
    			ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
    			tokenWriter.writeTokens( tokens );
    			page.setContents( updatedStream );
    		}
    		doc.save( outputFile );
    	}
    	finally
    	{
    		if( doc != null )
    		{
    			doc.close();
    		}
    	}
        }

    /**
     * This will open a PDF and replace a string if it finds it.
     * <br />
     * see usage() for commandline
     *
     * @param args Command line arguments.
     */
    public static void main(String[] args)
    {
        PDFModifier app = new PDFModifier();
        try
        {
          //  if( args.length != 4 )
          //  {
           //     app.usage();
          //  }
         //   else
         //   {
                //app.doIt( args[0], args[1], args[2], args[3] );
            	app.doIt( "D:/test_input1.pdf","D:/test_output1.pdf","","" );
        //    }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * This will print out a message telling how to use this example.
     */
    private void usage()
    {
        System.err.println( "usage: " + this.getClass().getName() +
            " <input-file> <output-file> <search-string> <Message>" );
    }
}
